/* +------------------------------------------------------------------------+
   |                     Mobile Robot Programming Toolkit (MRPT)            |
   |                          https://www.mrpt.org/                         |
   |                                                                        |
   | Copyright (c) 2005-2019, Individual contributors, see AUTHORS file     |
   | See: https://www.mrpt.org/Authors - All rights reserved.               |
   | Released under BSD License. See: https://www.mrpt.org/License          |
   +------------------------------------------------------------------------+ */

#include "io-precomp.h"  // Precompiled headers

#include <mrpt/core/exceptions.h>
#include <mrpt/core/reverse_bytes.h>
#include <mrpt/io/CStream.h>
#include <cstdarg>
#include <cstring>  // strlen()
#include <iostream>
#include <vector>

//#include "internal_class_registry.h"

using namespace mrpt;
using namespace mrpt::io;
using namespace std;

CStream::~CStream() = default;
/*---------------------------------------------------------------
			Writes an elemental data type to stream.
 ---------------------------------------------------------------*/
int CStream::printf(const char* fmt, ...)
{
	MRPT_START

	if (!fmt) throw std::runtime_error("fmt in CStream::printf cannot be NULL");

	int result = -1, length = 1024;
	vector<char> buffer;
	while (result == -1)
	{
		buffer.resize(length + 10);

		va_list args;  // This must be done WITHIN the loop
		va_start(args, fmt);
#if defined(_MSC_VER)
		result = ::vsnprintf_s(&buffer[0], length, _TRUNCATE, fmt, args);
#else
		result = ::vsnprintf(&buffer[0], length, fmt, args);
#endif
		va_end(args);

		// Truncated?
		if (result >= length) result = -1;
		length *= 2;
	}

	size_t l = strlen(&buffer[0]);
	this->Write(&buffer[0], (int)l);

	return result;

	MRPT_END
}

/*-------------------------------------------------------------
Reads from the stream until a '\n' character is found ('\r' characters are
ignored).
return false on EOF or any other read error.
-------------------------------------------------------------*/
bool CStream::getline(std::string& out_str)
{
	out_str.clear();
	try
	{
		for (;;)
		{
			size_t N = out_str.size();
			out_str.resize(N + 1);
			if (!Read(&out_str[N], 1)) return false;

			// New char read:
			if (out_str[N] == '\r')
			{
				out_str.resize(N);  // Ignore.
			}
			else if (out_str[N] == '\n')
			{
				out_str.resize(N);  // End of line!
				return true;  // Ok.
			}
		}
	}
	catch (...)
	{  // Any read error:
		return false;
	}
}
